package com.qiudao.commonutil.util;


import com.qiudao.commonutil.enums.CompanyTypeEnum;
import org.apache.commons.lang3.StringUtils;

import java.util.UUID;

/**
 * Description: 生成流水号和主键ID
 * @author: gdc
 * @date: 2019/9/1
 * @version 1.0
 */
public class UUIDUtils {
    private static final int ID_LENGTH = 32;
    private static final int INT_BIT = 8;
    private static final int STR_BIT = 8;
    private static final int SHORT_BIT = 4;
    private static final int JVM_BIT = 8;
    private static final int HI = 32;

    private static short counter = (short) 0;

    private static final int JVM = (int) (System.currentTimeMillis() >>> JVM_BIT);

    /**
     * 格式化字符串型数据(占八位)
     *
     * @param stringVal 字符串型的值
     * @return 格式化后的结果
     */
    private static String format(String stringVal) {
        if (stringVal == null) {
            stringVal = "";
        }
        stringVal = stringVal.length() > STR_BIT ? stringVal.substring(
                stringVal.length() - STR_BIT, stringVal.length()) : stringVal;
        StringBuilder bud = new StringBuilder("00000000");
        bud.replace(STR_BIT - stringVal.length(), STR_BIT, stringVal);
        return bud.toString();
    }

    /**
     * 格式化字符串型数据(占12位)
     *
     * @param stringVal 字符串型的值
     * @return 格式化后的结果
     */
    private static String format2(String stringVal) {
        if (stringVal == null) {
            stringVal = "";
        }
        stringVal = stringVal.length() > STR_BIT ? stringVal.substring(
                stringVal.length() - STR_BIT, stringVal.length()) : stringVal;
        StringBuilder bud = new StringBuilder("000000000000");
        bud.replace(STR_BIT - stringVal.length(), STR_BIT, stringVal);
        return bud.toString();
    }

    /**
     * 格式化int型数据(占八位)
     *
     * @param intVal int型的值
     * @return 格式化后的字符串
     */
    private static String format(int intVal) {
        String formatted = Integer.toHexString(intVal);
        StringBuilder bud = new StringBuilder("00000000");
        bud.replace(INT_BIT - formatted.length(), INT_BIT, formatted);
        return bud.toString();
    }

    /**
     * 格式化short型数据(占四位)
     *
     * @param shortVal short型的值
     * @return 格式化后的字符串
     */
    private static String format(short shortVal) {
        String formatted = Integer.toHexString(shortVal);
        StringBuilder bud = new StringBuilder("0000");
        bud.replace(SHORT_BIT - formatted.length(), SHORT_BIT, formatted);
        return bud.toString();
    }

    /**
     * 得到JVM的启动时间
     *
     * @return JVM的启动时间
     */
    private static int getJVM() {
        return JVM;
    }

    /**
     * 得到高位时间(short类型)
     *
     * @return 高位时间
     */
    private static short getHiTime() {
        return (short) (System.currentTimeMillis() >>> HI);
    }

    /**
     * 得到低位时间(int类型)
     *
     * @return 低位时间
     */
    private static int getLoTime() {
        return (int) System.currentTimeMillis();
    }

    /**
     * 得到当前计数(不会重复)
     *
     * @return 当前计数
     */
    private static short getCount() {
        synchronized (UUIDUtils.class) {
            if (counter < 0) {
                counter = 0;
            }
            return counter++;
        }
    }

    /**
     * 获取UUID的值
     *
     * @return UUID
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", ""); // 去掉UUID中的“-”符号
    }

    private static String getUUID(String companyCode) {
        StringBuilder stb = new StringBuilder(ID_LENGTH);
        stb.append(format(companyCode)); //8
        stb.append(format(getJVM()));  //8
        stb.append(format(getHiTime())); //4
        stb.append(format(getLoTime())); //8
        stb.append(format(getCount())); //4
        return stb.toString();
    }

    private static String getUUID2(String companyCode) {
        StringBuilder stb = new StringBuilder(ID_LENGTH);
        stb.append(format2(companyCode)); //12
        stb.append(format(getJVM()));  //8
        stb.append(format(getLoTime())); //8
        stb.append(format(getCount())); //4
        return stb.toString();
    }


    /**
     * 根据公司类型生成流水号或者主键ID
     * 0：总公司  --> 4位公司编码
     * 1：公司总部  --> 8位公司编码
     * 2：营业厅 -->12位公司编码
     *
     * @param type        公司类型
     * @param companyCode 公司编码
     * @return 生成的流水号32位
     */
    public static String getUUID(Short type, String companyCode) {
        if (type.equals(CompanyTypeEnum.GOLDCARD.getCode())) {
            Assert.isTrue(companyCode != null && companyCode.length() == 4, "总公司编码必须是4位的数字!");
            return getUUID(StringUtils.leftPad(companyCode, INT_BIT, "0"));
        }

        if (type.equals(CompanyTypeEnum.BRAND.getCode())) {
            Assert.isTrue(companyCode != null && companyCode.length() == 8, "公司总部编码必须是8位的数字!");
            return getUUID(companyCode);
        }

        if (type.equals(CompanyTypeEnum.BUSINESS_HALL.getCode())) {
            Assert.isTrue(companyCode != null && companyCode.length() == 12, "营业厅编码必须是12位的数字!");
            return getUUID2(companyCode);
        }

        return getUUID();
    }

}
